package com.cskaoyan.javase.oop1._10static._5exercise;

/**
 * 读程序题
 * 静态成员变量的默认初始化以及它的显式赋值
 * 都会在该类的类加载过程中执行
 *
 * 启动Demo类的main方法,触发Demo类的类加载
 * 在该类类加载的过程中,要完成静态成员变量的默认初始化以及显式赋值
 *
 * 要想完成Demo类的类加载
 * 需要new创建Cat的对象
 *
 * 要想创建Cat对象,需要先类加载Cat
 * 于是触发Cat类的类加载
 *
 * 要想完成Cat类的类加载,需要new创建Dog类的对象
 * 于是接着触发Dog类的类加载
 *
 * Dog类的类加载要想完成,需要完成静态成员变量的显式赋值
 *
 * 以上过程:
 *      类加载是可以连环触发的,第一次碰到类加载的时机
 *      就会触发该类的类加载
 *      类加载先触发的,反而最后结束
 *      最后触发的,反而最先结束
 *      这就很符合方法栈帧"先进后出"的特点
 *
 * 这是因为JVM在类加载某个类的时候,会将该类需要在类加载过程中执行的代码,封装成一个方法
 * 这个方法一般叫"cliint"方法
 * clinit就是类加载过程中执行方法的方法栈帧
 * 哪些代码需要在类加载过程中执行:
 *      1.静态成员变量的显式赋值
 *
 * 以上完成了本代码中,三个类的类加载,并且类加载只有一次
 * 不需要再次考虑了
 *
 * @since 16:42
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    // 静态成员变量的显式赋值,需要在类加载过程中执行
    static Cat cat = new Cat();
    Dog dog = new Dog();
    Dog dog2;
    static Dog dog3;

    public static void main(String[] args) {
        System.out.println("hello world!");
        // 这时该代码中的三个类都已经完成类加载了,所以已经不需要再次类加载了,new对象就直接去找构造器就可以,不需要考虑静态成员了
        Demo d = new Demo();
    }

    public Demo() {
        System.out.println("demo");
    }
}

class Cat {
    static Dog dog = new Dog();

    public Cat() {
        System.out.println("cat");
    }
}

class Dog {
    static int num = 10;
    public Dog() {
        System.out.println("dog");
    }
}